package com.wtf.dsp.admin.core.provider;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.extension.toolkit.SqlParserUtils;
import com.wtf.dsp.admin.core.parser.MapperXmlResourceParser;
import com.wtf.dsp.admin.enums.DataChangeType;
import com.wtf.dsp.admin.config.CustomMybatisConfiguration;
import com.wtf.dsp.admin.util.MapperXmlUtil;
import com.wtf.dsp.admin.core.DsConfig;
import com.wtf.dsp.admin.core.executor.AbstractExecutor;
import com.wtf.dsp.admin.core.model.DataSourceInfo;
import com.wtf.dsp.admin.core.model.DataSourceConfigInfo;
import com.wtf.dsp.admin.core.model.MappserSqlConfig;
import com.wtf.dsp.admin.core.model.SqlInfo;
import com.wtf.dsp.admin.core.model.api.DataChangeRequest;
import com.wtf.dsp.admin.core.parser.ParamNameResolver;
import com.wtf.dsp.admin.enums.CommonErrorEnum;
import com.wtf.dsp.admin.enums.SqlMybatisXml;
import com.wtf.dsp.admin.exception.WtfDspException;
import com.wtf.dsp.admin.model.ExcSql;
import com.wtf.dsp.admin.model.PageSql;
import com.wtf.dsp.admin.model.dto.DsSqlDTO;
import com.wtf.dsp.admin.util.SqlInterceptor;
import com.wtf.dsp.core.model.ExecSqlRequest;
import com.wtf.dsp.admin.core.parser.SqlParser;
import com.wtf.dsp.core.constant.NsConstant;
import com.wtf.dsp.core.enums.SqlType;
import com.wtf.dsp.core.util.PageUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.scheduling.annotation.Async;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 * ClassName: AbstractMybatisConfigExecutor
 * Description:
 * date: 2024/3/11 9:55
 *
 * @author linhuanyou
 * @version 1.0
 */
@Slf4j
public abstract class AbstractMybatisConfigProvider extends AbstractExecutor implements DsConfig ,InitializingBean{
    //读写锁
    private ReadWriteLock lock = new ReentrantReadWriteLock();

    private static volatile ConcurrentMap<String, DataSourceConfigInfo> NS_DS_MYBATIS_CONFIG = new ConcurrentHashMap<>();

    private AbstractWtfDynamicDataSourceProvider dataSourceProvider;

    private Thread refreshThread;

    private volatile long exceTime ;

    private volatile boolean toStop = false;

    private volatile boolean frist = false;

    private int refreshTime = 1;

    public AbstractMybatisConfigProvider(AbstractWtfDynamicDataSourceProvider dataSourceProvider) {
        this.dataSourceProvider = dataSourceProvider;
    }

    @Override
    protected void initExecutors() {
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        initNsMybatisConfig();
        start();
    }

    private synchronized void initNsMybatisConfig() {
         new Thread(new Runnable() {
            @Override
            public void run() {
                log.info("+++++++++++ Init Ns Mybatis Config Begin   >>>> : {}", DateUtil.formatDateTime(new Date()));
                List<DataSourceInfo> dataSources = dataSourceProvider.loadDataSources();
                initDsMybatisConfig(dataSources);
                log.info("+++++++++++ Init Ns Mybatis Config Success >>>> : {}", DateUtil.formatDateTime(new Date()));
            }
        }).start();
    }

    private synchronized void initDsMybatisConfig(List<DataSourceInfo> dataSourceInfos) {
        for (DataSourceInfo dataSourceInfo : dataSourceInfos) {
            initDsMybatisConfig(dataSourceInfo);
        }
    }

    public synchronized void initDsMybatisConfig(DataSourceInfo dataSourceInfo) {
        try {
            refreshDataSourceMybatisConfig(dataSourceInfo);
        } catch (Exception e){
            log.error("Refresh Dynamic DataSource Config Error",e);
            try {
                clearDynamicDataSource(dataSourceInfo.getNs(), dataSourceInfo.getDs());
            } catch (Exception e1){
                throw e1;
            }
            throw e;
        }
    }

    /**
     * 获取数据源的配置信息
     * @param ns
     * @param ds
     * @return
     */
    @Override
    public DataSourceConfigInfo getDsConfig(String ns, String ds) {
        return NS_DS_MYBATIS_CONFIG.get(NsConstant.nsGroupDs(ns,ds));
    }

    public DataSourceConfigInfo getDataSourceMapperConfig(String ns, String ds) {
        DataSourceConfigInfo dsMapperConfig = getDsConfig(ns,ds);
        if(dsMapperConfig == null){
            synchronized (this){
                dsMapperConfig = getDsConfig(ns,ds);
                if(dsMapperConfig == null){
                    DataSourceInfo dataSource = dataSourceProvider.getDataSource(ns,ds);
                    if(dataSource != null){
                        initDsMybatisConfig(dataSource);
                    }
                }
            }
        }
        dsMapperConfig = getDsConfig(ns,ds);
        if(dsMapperConfig == null){
            throw new WtfDspException(CommonErrorEnum.DATA_SOURCE_NOT_EXIST);
        }
        return dsMapperConfig;
    }

    @Override
    public void delDsConfig(String ns, String ds) {
        NS_DS_MYBATIS_CONFIG.remove(NsConstant.nsGroupDs(ns,ds));
    }

    /**
     * 刷新数据源的Mybatis映射文件配置
     * @param dataSourceInfo
     */
    public synchronized void refreshDataSourceMybatisConfig(DataSourceInfo dataSourceInfo){
        String nsGroupDs = NsConstant.nsGroupDs(dataSourceInfo.getNs(),dataSourceInfo.getDs());
        if(NS_DS_MYBATIS_CONFIG.containsKey(nsGroupDs)){
            throw new WtfDspException(CommonErrorEnum.DATA_SOURCE_EXIST);
        }
        DataSourceConfigInfo dataSourceMapperConfig = new DataSourceConfigInfo();
        CustomMybatisConfiguration targetConfiguration = new CustomMybatisConfiguration();
        dataSourceMapperConfig.setTargetConfiguration(targetConfiguration);
        dataSourceMapperConfig.setDbType(dataSourceInfo.getDbType());
        Map<String, MappserSqlConfig> mappserSqlConfigMap = new ConcurrentHashMap<>();
        dataSourceMapperConfig.setMapperConfigs(mappserSqlConfigMap);
        Map<String, SqlType> sqlTypeMap = new ConcurrentHashMap<>();
        dataSourceMapperConfig.setDataSourceInfo(dataSourceInfo);
        dataSourceMapperConfig.setSqlTypes(sqlTypeMap);
        //刷新Mapper的sql配置
        refreshMapperSqlConfig(dataSourceInfo.getNs(),dataSourceInfo.getDs(),"",dataSourceMapperConfig);
        //加载数据源连接池
        doLoadDynamicDataSource(dataSourceInfo);
        //内存
        NS_DS_MYBATIS_CONFIG.put(nsGroupDs,dataSourceMapperConfig);
        log.info("Load The Dynamic DataSource : {}", nsGroupDs);
    }

    /**
     * 如果有必要重新刷新数据源的相关配置
     * @param dataSourceInfo
     */
    public synchronized void refreshDataSourceIfNecessary(DataSourceInfo dataSourceInfo){
        String nsGroupDs = NsConstant.nsGroupDs(dataSourceInfo.getNs(),dataSourceInfo.getDs());
        if(!NS_DS_MYBATIS_CONFIG.containsKey(nsGroupDs)){
            refreshDataSourceMybatisConfig(dataSourceInfo);
        } else {
            DataSourceConfigInfo dataSourceConfigInfo = NS_DS_MYBATIS_CONFIG.get(nsGroupDs);
            DataSourceInfo oldDsInfo = dataSourceConfigInfo.getDataSourceInfo();
            if(!oldDsInfo.md5().equals(dataSourceInfo.md5())){
                log.info("Update DataSource Info Old : {} ,New : {}",oldDsInfo,dataSourceInfo);
                doLoadDynamicDataSource(dataSourceInfo);
                dataSourceConfigInfo.setDataSourceInfo(dataSourceInfo);
            }
        }
    }

    /**
     * 重新刷新数据源的相关配置
     * @param ns
     * @param ds
     */
    public synchronized void refreshDataSource(String ns , String ds ){
        refreshDataSourceIfNecessary(dataSourceProvider.getDataSource(ns,ds));
    }

    /**
     *  刷新Mapper映射的SQL配置
     * @param ns
     * @param ds
     * @param mns
     * @param dataSourceConfigInfo
     */
    private void refreshMapperSqlConfig(String ns, String ds, String mns, DataSourceConfigInfo dataSourceConfigInfo){
        synchronized (dataSourceConfigInfo){
            Map<String, List<SqlInfo>> mnsSqlsMap = getSqls(ns, ds).stream().filter(e->{
                if(StringUtils.isNotBlank(e.getMns())){
                    if(StringUtils.isBlank(mns)){
                        return true;
                    } else {
                        return mns.equals(e.getMns());
                    }
                } else {
                    return false;
                }
            }).collect(Collectors.groupingBy(SqlInfo::getMns));
            refreshMapperSqlConfig(ns,ds,mnsSqlsMap,dataSourceConfigInfo);
        }
    }

    /**
     * 刷新Mapper映射的SQL配置
     * @param ns
     * @param ds
     * @param mnsSqlsMap
     * @param dataSourceConfigInfo
     */
    private void refreshMapperSqlConfig(String ns, String ds, Map<String, List<SqlInfo>> mnsSqlsMap, DataSourceConfigInfo dataSourceConfigInfo){
        mnsSqlsMap.forEach(new BiConsumer<String, List<SqlInfo>>() {
            @Override
            public void accept(String mns, List<SqlInfo> sqlInfos) {
                refreshMapperSqlConfig(ns,ds,mns,sqlInfos,dataSourceConfigInfo);
            }
        });
    }

    /**
     * 刷新Mapper映射的SQL配置
     * @param ns
     * @param ds
     * @param mns
     * @param sqlInfos
     * @param dataSourceConfigInfo
     */
    private void refreshMapperSqlConfig(String ns, String ds, String mns, List<SqlInfo> sqlInfos, DataSourceConfigInfo dataSourceConfigInfo) {
        synchronized (dataSourceConfigInfo){
            Map<String, MappserSqlConfig> mapperConfigs = dataSourceConfigInfo.getMapperConfigs();
            MappserSqlConfig mappserSqlConfig = mapperConfigs.containsKey(mns) ? mapperConfigs.get(mns) : new MappserSqlConfig();
            dataSourceConfigInfo.getMapperConfigs().put(mns, mappserSqlConfig);
            List<String> mnsSqlList = new ArrayList<>();
            sqlInfos = sqlInfos.stream().filter(e->{return StringUtils.isNotBlank(e.getSqlId());}).collect(Collectors.toList());
            sqlInfos.forEach(new Consumer<SqlInfo>() {
                @Override
                public void accept(SqlInfo sqlInfo) {
                    dataSourceConfigInfo.getSqlTypes().put(NsConstant.mapperNamespace(ns,ds,mns,sqlInfo.getSqlId()),sqlInfo.getSqlType());
                    mnsSqlList.add(sqlInfo.getSqlXml());
                }
            });
            String mapperXml = MapperXmlUtil.mapperXmlStr(NsConstant.mapperNamespace(ns, ds, mns), mnsSqlList);
            mappserSqlConfig.setSqlInfos(sqlInfos);
            mappserSqlConfig.setMnsMd5(DigestUtil.md5Hex(mapperXml));
            refreshMapperResource(ns,ds,mns,mapperXml,dataSourceConfigInfo.getTargetConfiguration());
        }
    }



    protected abstract List<SqlInfo> getSqls(String ns, String ds) ;

    public String validateSql(SqlType sqlType,String sqlId,String sqlStatement){
        String sqlStatemenTrim = sqlStatement.trim();
        boolean validateSql = sqlStatemenTrim.startsWith(sqlType.toString().toLowerCase()) || sqlStatemenTrim.startsWith(sqlType.toString().toUpperCase());
        if(!validateSql){
            if(SqlType.SELECT.equals(sqlType)){
                boolean withSelectSql = sqlStatemenTrim.startsWith("with") || sqlStatemenTrim.startsWith("WITH");
                if(!withSelectSql){
                    throw new WtfDspException(CommonErrorEnum.MAPPER_SQL_VALIDATE);
                }
            } else {
                throw new WtfDspException(CommonErrorEnum.MAPPER_SQL_VALIDATE);
            }
        }
        return SqlMybatisXml.obtainSqlstatementXml(sqlType,sqlId,sqlStatemenTrim);
    }

    /**
     * 刷新Mapper的xml资源
     * @param ns
     * @param ds
     * @param mns
     * @param mapperXml
     * @param targetConfiguration
     */
    public void refreshMapperResource(String ns, String ds, String mns, String mapperXml, CustomMybatisConfiguration targetConfiguration) {
        targetConfiguration.delLoadedResources(ns,ds,mns);
        MapperXmlResourceParser.loadMapperResource(new ByteArrayResource(mapperXml.getBytes(), NsConstant.mapperNamespace(ns, ds, mns)), targetConfiguration);
    }

    /**
     * 卸载数据源连接池
     * @param ns
     * @param ds
     */
    public synchronized void clearDynamicDataSource(String ns, String ds) {
        delDsConfig(ns,ds);
        dataSourceProvider.removeDataSource(ns,ds);
    }

    /**
     * 加载数据源连接池
     * @param dataSourceInfo
     */
    public synchronized void doLoadDynamicDataSource(DataSourceInfo dataSourceInfo) {
        //先删除旧重名数据源
        dataSourceProvider.removeDataSource(dataSourceInfo.getNs(),dataSourceInfo.getDs());
        //加载最新的数据源
        dataSourceProvider.addDataSources(dataSourceInfo);
    }

    @Async
    public synchronized void reLoadDynamicDataSource(String ns,String ds) {
        String nsGroupDs = NsConstant.nsGroupDs(ns, ds);
        if(NS_DS_MYBATIS_CONFIG.containsKey(nsGroupDs)){
            DataSourceInfo dataSourceInfo = NS_DS_MYBATIS_CONFIG.get(nsGroupDs).getDataSourceInfo();
            doLoadDynamicDataSource(dataSourceInfo);
        } else {
            DataSourceInfo dataSourceInfo = dataSourceProvider.getDataSource(ns,ds);
            initDsMybatisConfig(dataSourceInfo);
        }
    }

    public ExcSql doObtainSql(ExecSqlRequest request) {
        DataSourceConfigInfo dsMapperConfig = getDataSourceMapperConfig(request.getNs(),request.getDs());
        CustomMybatisConfiguration targetConfiguration = dsMapperConfig.getTargetConfiguration();
        String nsDsMnsSqlGroup = NsConstant.mapperNamespace(request.getNs(), request.getDs(), request.getMns(), request.getSqlId());
        if(!targetConfiguration.mappedStatements().containsKey(nsDsMnsSqlGroup)){
            refreshMapperSqlConfig(request.getNs(),request.getDs(),request.getMns(),dsMapperConfig);
        }
        MappedStatement mappedStatement = targetConfiguration.getMappedStatement(nsDsMnsSqlGroup);
        if(mappedStatement == null){
            throw new WtfDspException(CommonErrorEnum.MAPPER_SQL_NOT_EXIST);
        }
        Map<String, Object> params = request.getParams();
        Object namedParams = ParamNameResolver.getNamedParams(params);
        BoundSql boundSql = mappedStatement.getBoundSql(namedParams);
        String execSql = SqlInterceptor.formatSql(targetConfiguration, boundSql);
        ExcSql excSql = new ExcSql();
        excSql.setExcSql(execSql);
        excSql.setDbType(dsMapperConfig.getDbType());
        excSql.setSqlType(dsMapperConfig.getSqlTypes().get(NsConstant.mapperNamespace(request.getNs(),request.getDs(),request.getMns(),request.getSqlId())));
        return excSql;
    }

    /**
     * 刷新Mapper，以及对应sql的配置信息
     * @param ns
     * @param ds
     * @param mns
     */
    public void refreshMapperSqlConfig(String ns, String ds, String mns){
        DataSourceConfigInfo dsMapperConfig = getDsConfig(ns,ds);
        synchronized (dsMapperConfig){
            refreshMapperSqlConfig(ns,ds,mns,dsMapperConfig);
        }
    }

    /**
     *
     * @param ns
     * @param ds
     * @param mns
     */
    public void removeMapperSqlConfig(String ns, String ds, String mns){
        DataSourceConfigInfo dsMapperConfig = getDsConfig(ns,ds);
        synchronized (dsMapperConfig){
            Map<String, MappserSqlConfig> mapperConfigs = dsMapperConfig.getMapperConfigs();
            mapperConfigs.remove(mns);
            dsMapperConfig.getTargetConfiguration().delLoadedResources(ns,ds,mns);
        }
    }

    public void start(){
        this.exceTime = System.currentTimeMillis();
        refreshThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (!toStop) {
                    if(frist){
                        try {
                            long now = System.currentTimeMillis();
                            if(now -  exceTime >= (refreshTime * 1000L * 30) ){
                                log.info(">>>>>>>>>>> Wtf Dsp Dynamic DataSource Thread Executor Begin Time >>>> :{}", DateUtil.formatDateTime(new Date(now)));
                                exceTime = now;
                                dataChangeRefresh();
                                log.info(">>>>>>>>>>> Wtf Dsp Dynamic DataSource Thread Executor Success Time >> :{}",DateUtil.formatDateTime(new Date()));
                            }
                        } catch (Exception e) {
                            if (!toStop) {
                                log.error(">>>>>>>>>>> Wtf Dsp Dynamic DataSource monitor thread error  :{}", e);
                            }
                        }
                    } else {
                        frist = true;
                        log.error(">>>>>>>>>>> Wtf Dsp Dynamic DataSource monitor thread start :{}", frist);
                    }
                    try {
                        TimeUnit.SECONDS.sleep(refreshTime * 10L);
                    } catch (InterruptedException e) {
                        if (!toStop) {
                            log.error(">>>>>>>>>>> Wtf Dsp Dynamic DataSource monitor thread error:{}", e);
                        }
                    }
                }
                log.info(">>>>>>>>>>> Wtf Dsp Dynamic DataSource thread stop : {}",frist);
            }
        });
        refreshThread.setDaemon(true);
        refreshThread.setName("Wtf Dsp Dynamic DataSource Monitor");
        refreshThread.start();
    }

    public synchronized void dataChangeRefresh(){
        List<String> oldNsDsKeys = NS_DS_MYBATIS_CONFIG.keySet().stream().collect(Collectors.toList());
        //数据量问题
        List<SqlInfo> sqlInfos = getSqls(null, null);
        List<String> newNsDsKeys = sqlInfos.stream().map(e -> {
            return NsConstant.nsGroupDs(e.getNs(), e.getDs());
        }).collect(Collectors.toList());
        //剔除已删除的数据源
        CollUtil.subtract(oldNsDsKeys, newNsDsKeys).forEach(new Consumer<String>() {
            @Override
            public void accept(String ns_ds) {
                log.info(">>>>>>>>>>> Remove Dynamic DataSource ns_ds : {}",ns_ds);
                String[] ns_ds_split = ns_ds.split("_");
                clearDynamicDataSource(ns_ds_split[0],ns_ds_split[1]);
            }
        });
        //判断更新当前内存中已存在的数据源及其Mybatis配置
        CollUtil.unionDistinct(oldNsDsKeys,newNsDsKeys).forEach(new Consumer<String>() {
            @Override
            public void accept(String ns_ds) {
                String[] ns_ds_split = ns_ds.split("_");
                String ns = ns_ds_split[0];
                String ds = ns_ds_split[1];
                DataSourceInfo dataSource = dataSourceProvider.getDataSource(ns, ds);
                refreshDataSourceIfNecessary(dataSource);
                Map<String, List<SqlInfo>> sqlInfosMap = sqlInfos.stream().filter(e -> {
                    return NsConstant.nsGroupDs(e.getNs(), e.getDs()).equals(ns_ds) && StringUtils.isNotBlank(e.getMns());
                }).collect(Collectors.groupingBy(SqlInfo::getMns));
                List<String> newMnsKeys = sqlInfosMap.keySet().stream().collect(Collectors.toList());
                List<String> oldMnsKeys = new ArrayList<>();
                if(NS_DS_MYBATIS_CONFIG.containsKey(ns_ds)){
                    oldMnsKeys = NS_DS_MYBATIS_CONFIG.get(ns_ds).getMapperConfigs().keySet().stream().collect(Collectors.toList());
                }
                //剔除已经删除的mns
                CollUtil.subtract(oldMnsKeys, newMnsKeys).forEach(new Consumer<String>() {
                    @Override
                    public void accept(String mns) {
                        log.info(">>>>>>>>>>> Remove MapperNamespace :{}",NsConstant.mapperNamespace(ns,ds,mns));
                        removeMapperSqlConfig(ns,ds,mns);
                    }
                });
                DataSourceConfigInfo dataSourceConfigInfo = NS_DS_MYBATIS_CONFIG.get(ns_ds);
                //判断更新当前内存中已存在的mns及其Mybatis配置
                CollUtil.intersectionDistinct(oldMnsKeys,newMnsKeys).forEach(new Consumer<String>() {
                    @Override
                    public void accept(String mns) {
                        MappserSqlConfig mappserSqlConfig = dataSourceConfigInfo.getMapperConfigs().get(mns);
                        List<SqlInfo> sqlInfos = sqlInfosMap.get(mns);
                        String mapperXml = MapperXmlUtil.mapperXmlStr(NsConstant.mapperNamespace(ns,ds, mns), sqlInfos.stream().map(SqlInfo::getSqlXml).collect(Collectors.toList()));
                        if(mappserSqlConfig == null || !DigestUtil.md5Hex(mapperXml).equals(mappserSqlConfig.getMnsMd5())){
                            log.info(">>>>>>>>>>> Update MapperNamespace :{}",NsConstant.mapperNamespace(ns,ds,mns));
                            refreshMapperSqlConfig(ns,ds,mns,sqlInfos,dataSourceConfigInfo);
                        }
                    }
                });
                //添加新增的mns
                CollUtil.subtract(newMnsKeys, oldMnsKeys).stream().forEach(new Consumer<String>() {
                    @Override
                    public void accept(String mns) {
                        log.info(">>>>>>>>>>> Add MapperNamespace :{}",NsConstant.mapperNamespace(ns,ds,mns));
                        refreshMapperSqlConfig(ns,ds,mns);
                    }
                });
            }
        });
        //添加新增的数据源
        CollUtil.subtract(newNsDsKeys, oldNsDsKeys).stream().forEach(new Consumer<String>() {
            @Override
            public void accept(String ns_ds) {
                String[] ns_ds_split = ns_ds.split("_");
                log.info(">>>>>>>>>>> Add Dynamic DataSource ns_ds : {}",ns_ds);
                initDsMybatisConfig(dataSourceProvider.getDataSource(ns_ds_split[0],ns_ds_split[1]));;
            }
        });
    }

    public void dataChangeRefresh(DataChangeRequest request){
        DataChangeType dataChangeType = request.getDataChangeType();
        switch (dataChangeType){
            case DS_INSERT:
                clearDynamicDataSource(request.getNs(),request.getDs());
                initDsMybatisConfig(dataSourceProvider.getDataSource(request.getNs(),request.getDs()));
                break;
            case DS_UPDATE:
                break;
            case DS_DELETE:
                clearDynamicDataSource(request.getNs(),request.getDs());
                break;
            case MNS_INSERT:
            case MNS_UPDATE:
                refreshMapperSqlConfig(request.getNs(),request.getDs(),request.getMns());
                break;
            case MNS_DELETE:
                removeMapperSqlConfig(request.getNs(),request.getDs(),request.getMns());
            default:
                break;
        }
    }

    public Object execute(ExecSqlRequest request) throws Exception {
        ExcSql execSql = doObtainSql(request);
        DsSqlDTO dsSqlDTO = new DsSqlDTO();
        dsSqlDTO.setDs(request.getDs());
        dsSqlDTO.setNs(request.getNs());
        dsSqlDTO.setMns(request.getMns());
        dsSqlDTO.setSqlId(request.getSqlId());
        dsSqlDTO.setDbType(execSql.getDbType());
        dsSqlDTO.setExcSql(execSql.getExcSql());
        dsSqlDTO.setSqlType(execSql.getSqlType());
        dsSqlDTO.setPage(request.getPage());
        dsSqlDTO.setLimit(request.getLimit());
        dsSqlDTO.setSqlResponseMapper(request.getSqlResponseMapper());
        TypeReference typeReference = null;
        switch (dsSqlDTO.getSqlResponseMapper()){
            case MAP_LIST:
                typeReference = new TypeReference<List>(){};
                break;
            case PAGE:
                typeReference = new TypeReference<PageUtils>(){};
                //分页查询的SQL需要分成查询总数和实际分页查询的SQL
                PageSql pageSql = new PageSql();
                pageSql.setPage(dsSqlDTO.getPage() == null || dsSqlDTO.getPage() == 0 ? 1 : dsSqlDTO.getPage());
                pageSql.setLimit(dsSqlDTO.getLimit() == null || dsSqlDTO.getLimit() == 0 ? 1 : dsSqlDTO.getLimit());
                pageSql.setExecSql(SqlParser.dialectSql(dsSqlDTO.getExcSql(),dsSqlDTO.getPage(),dsSqlDTO.getLimit(),dsSqlDTO.getDbType()));
                pageSql.setTotalSql(SqlParserUtils.getOptimizeCountSql(true,null,dsSqlDTO.getExcSql()).getSql());
                dsSqlDTO.setPageSql(pageSql);
                break;
            case MAP:
                typeReference = new TypeReference<Map>(){};
                break;
            default:
                throw new WtfDspException(CommonErrorEnum.ERROR_VALID);
        }
        return execute(dsSqlDTO,typeReference);
    }

    public <T> T execute(DsSqlDTO dsSqlDTO, TypeReference<T> clazz) throws Exception {
        return dataSourceProvider.doExecutor(dsSqlDTO, clazz);
    }

    public Object execute(DsSqlDTO dsSqlDTO) throws Exception {
        TypeReference typeReference = null;
        switch (dsSqlDTO.getSqlResponseMapper()){
            case MAP_LIST:
                typeReference = new TypeReference<List>(){};
                break;
            case PAGE:
                typeReference = new TypeReference<PageUtils>(){};
                break;
            case MAP:
                typeReference = new TypeReference<Map>(){};
                break;
            default:
                throw new WtfDspException(CommonErrorEnum.ERROR_VALID);
        }
        return execute(dsSqlDTO, typeReference);
    }

    /**
     * 数据库测试连接
     * @param dataSourceInfo
     * @return
     * @throws Exception
     */
    public Boolean testConnect(DataSourceInfo dataSourceInfo) throws Exception {
       return dataSourceProvider.testConnectDb(dataSourceInfo);
    }

    public Boolean testDriver(String  driverClass) {
        return dataSourceProvider.testDriver(driverClass);
    }


    public DataSourceInfo getDataSource(String sourceNs, String ds) {
        return dataSourceProvider.getDataSource(sourceNs,ds);
    }
}
